﻿#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>

#include <glib.h>
#include <gio/gio.h>
#include <libsoup/soup.h>

#include "json/json.h"
#include "http.h"
#include "httpext.h"
#include "util.h"
#include "jsonrpc_server.h"

static gboolean http_ext_download(SoupServer *server, SoupMessage *msg, GHashTable *query) {
	char *filename = g_hash_table_lookup(query, "file");
	GMappedFile *mapping = g_mapped_file_new(filename, FALSE, NULL );
	SoupBuffer *buffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(mapping),
			g_mapped_file_get_length(mapping), mapping, (GDestroyNotify) g_mapped_file_unref);
	soup_message_body_append_buffer(msg->response_body, buffer);
	//TODO:soup_message_headers_set_content_disposition
	char *disposition = g_strdup_printf("attachment; filename=%s", strrchr(filename, '/') + 1);
	soup_message_headers_append(msg->response_headers, HTTP_HEADER_CONTENT_DISPOSITION, disposition);
	soup_message_headers_append(msg->response_headers, HTTP_HEADER_PRAGMA, "No-cache");
	soup_message_headers_append(msg->response_headers, HTTP_HEADER_CACHE_CONTROL, "No-cache");
	soup_message_headers_append(msg->response_headers, HTTP_HEADER_EXPIRES, "0");
	soup_message_headers_append(msg->response_headers, HTTP_HEADER_CONTENT_TYPE, "application/octet-stream");
	soup_buffer_free(buffer);

	g_free(disposition);

	return TRUE;
}

static gboolean http_ext_file(SoupServer *server, SoupMessage *msg, GHashTable *query) {
	gboolean ret = FALSE;
	char *filename = g_hash_table_lookup(query, "name");
	GMappedFile *mapping = g_mapped_file_new(filename, FALSE, NULL );
	if (mapping) {
		SoupBuffer *buffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(mapping),
				g_mapped_file_get_length(mapping), mapping, (GDestroyNotify) g_mapped_file_unref);
		soup_message_body_append_buffer(msg->response_body, buffer);
		ret = TRUE;
	}

	return ret;
}

static gboolean http_ext_info(SoupServer *server, SoupMessage *msg, GHashTable *query) {
	json_object *info = json_object_new_object();

	//GFileType enum
	json_object *_GFileType = json_object_new_object();
	json_object_object_add(_GFileType, "G_FILE_TYPE_UNKNOWN", json_object_new_int(G_FILE_TYPE_UNKNOWN));
	json_object_object_add(_GFileType, "G_FILE_TYPE_REGULAR", json_object_new_int(G_FILE_TYPE_REGULAR));
	json_object_object_add(_GFileType, "G_FILE_TYPE_DIRECTORY", json_object_new_int(G_FILE_TYPE_DIRECTORY));
	json_object_object_add(_GFileType, "G_FILE_TYPE_SYMBOLIC_LINK", json_object_new_int(G_FILE_TYPE_SYMBOLIC_LINK));
	json_object_object_add(_GFileType, "G_FILE_TYPE_SPECIAL", json_object_new_int(G_FILE_TYPE_SPECIAL));
	json_object_object_add(_GFileType, "G_FILE_TYPE_SHORTCUT", json_object_new_int(G_FILE_TYPE_SHORTCUT));
	json_object_object_add(_GFileType, "G_FILE_TYPE_MOUNTABLE", json_object_new_int(G_FILE_TYPE_MOUNTABLE));
	json_object_object_add(info, "GFileType", _GFileType);

	//GLib Version
	char version[32];
	sprintf(version, "%d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
	json_object_object_add(info, "GLibVersion", json_object_new_string(version));

	//IP list
	json_object *ip = json_object_new_array();
	GResolver *resolver = g_resolver_get_default();
	GList *ip_list = g_resolver_lookup_by_name(resolver, g_get_host_name(), NULL, NULL );
	if (g_list_length(ip_list) > 0) {
		for (GList *it = ip_list; it; it = it->next) {
			GInetAddress *addr = it->data;
			json_object_array_add(ip, json_object_new_string(g_inet_address_to_string(addr)));
		}
	}
	g_list_free(ip_list);
	g_object_unref(resolver);
	json_object_object_add(info, "IP", ip);

	//Server port
	json_object_object_add(info, "Port", json_object_new_int(soup_server_get_port(server)));

	const char *json = json_object_to_json_string(info);
	soup_message_body_append(msg->response_body, SOUP_MEMORY_COPY, json, strlen(json));

	json_object_put(info);

	return TRUE;
}

gboolean http_ext(SoupServer *server, SoupMessage *msg) {
	gboolean ret = FALSE;

	if (msg->method == SOUP_METHOD_GET) {
		SoupURI *uri = soup_message_get_uri(msg);
		if (uri->query) {
			GHashTable *query = soup_form_decode_urlencoded(uri->query);

			char *cmd = g_hash_table_lookup(query, "__cmd__");
			if (cmd) {
				if (g_strcasecmp(cmd, "download") == 0) {
					ret = http_ext_download(server, msg, query);
				} else if (g_strcasecmp(cmd, "file") == 0) {
					ret = http_ext_file(server, msg, query);
				} else if (g_strcasecmp(cmd, "info") == 0) {
					ret = http_ext_info(server, msg, query);
				}
			}
			g_hash_table_destroy(query);
		}
	}

	if (ret) {
		soup_message_set_status(msg, SOUP_STATUS_OK);
	}

	return ret;
}
